Python Basics with Numpy

(from CS230-Deep-Learning)

이 과제 후 당신은 다음을 할 수 있게 됩니다.

iPython Notebooks

iPython 노트북은 웹 페이지에 포함 된 대화 형 코딩 환경입니다. 이 수업에서는 iPython 노트북을 사용하게 됩니다. ### START CODE HERE ### 및 ### END CODE HERE ### 주석 사이에 코드를 작성하기만하면 됩니다. 코드를 작성한 후 "SHIFT"+"ENTER"를 누르거나 노트북 상단 표시 줄에 있는 "Run Cell"(재생 기호로 표시)을 클릭하여 셀을 실행할 수 있습니다.

(1) 연습 : 아래 셀에서 test를 "Hello World"로 설정하여 "Hello World"를 인쇄하고 아래 셀을 실행합니다.

Expected output: test: Hello World

1. numpy로 기본 함수 만들기 ¶

Numpy는 Python의 과학 컴퓨팅을 위한 기본 패키지입니다. 대규모 커뮤니티 (www.numpy.org)에서 관리합니다. 이 연습에서는 np.exp, np.log 및 np.reshape 와 같은 몇 가지 주요 numpy 함수를 학습합니다. 향후 과제을 위해 이러한 함수를 사용하는 방법을 알아야 합니다.

1.1 시그모이드 함수, np.exp( )

np.exp( )를 사용하기 전에 math.exp( )를 사용하여 시그모이드 함수를 구현합니다. 그러면 np.exp( )가 math.exp( )보다 더 나은 이유를 알 수 있습니다.

(2) 연습 : 실수 $x$의 시그모이드를 반환하는 함수를 만듭니다. 지수 함수에는 math.exp(x)를 사용하십시오.

참고 : $sigmoid(x) = \frac{1}{1 + e^{-x}} $는 때때로 로지스틱 함수라고도 합니다. 머신러닝(로지스틱 회귀)뿐 아니라 딥 러닝에서도 사용되는 비선형 함수입니다.

특정 패키지에 속하는 함수를 참조하려면 package_name.function( )을 사용하여 호출할 수 있습니다. 아래 코드를 실행하여 math.exp( )를 사용한 예제를 확인하십시오.

Expected output:

basic_sigmoid(3) 0.9525741268224334

"math" 라이브러리는 함수의 입력이 실수이기 때문에 실제로 딥 러닝에서 거의 사용하지 않습니다. 딥 러닝에서 우리는 주로 행렬과 벡터를 입력으로 사용합니다. 이것이 numpy가 더 유용한 이유입니다.

실제로 $x=(x_1, x_2, ..., x_n)$이 행 벡터이면 np.exp(x)는 x의 모든 요소에 지수 함수를 적용합니다. 따라서 출력은 다음과 같습니다. np.exp(x) $ =(e^{x_1}, e^{x_2}, \cdots, e^{x_n})$

또한 x가 벡터인 경우 $s = x + 3$ 또는 $s = \frac{1}{x} $와 같은 Python 연산은 s를 x와 동일한 크기의 벡터로 출력합니다.

(3) 연습 : numpy를 사용하여 sigmoid 함수를 구현합니다.

지시 : $x$는 이제 실수, 벡터 또는 행렬이 될 수 있습니다. 이러한 모양 (벡터, 행렬 ...)을 표현하기 위해 numpy에서 사용하는 데이터 구조를 numpy 배열이라고합니다. 지금은 더 많이 알 필요가 없습니다.

$$\text{ For } x \in \mathbb{R}^n, \quad \text{sigmoid}(x) = \text{sigmoid}\left( \begin{matrix} x_1\\ x_2\\ \vdots \\ x_n \end{matrix}\right) = \left( \begin{matrix} {1 \over 1 + e^{-x_1}} \\ {1 \over 1 + e^{-x_2}}\\ \vdots \\ {1 \over 1 + e^{-x_n}}\end{matrix}\right) $$

Expected Output:

sigmoid([1,2,3]) array([ 0.73105858, 0.88079708, 0.95257413])

1.2 Sigmoid gradient

강의에서 보았듯이 역전파를 사용하여 손실 함수를 최적화하려면 그래디언트를 계산해야 합니다. 첫 번째 그래디언트 함수를 코딩해 보겠습니다.

(4) 연습 : sigmoid_grad() 함수를 구현하여 입력 x에 대한 시그모이드 함수의 기울기를 계산합니다. 공식은 다음과 같습니다.

$$ \text{sigmoid_derivative}(x) = \sigma'(x) = \sigma(x)(1-\sigma(x)) \tag{2} $$

종종 이 함수를 두 단계로 코딩합니다.

  1. s를 x의 시그모이드로 설정합니다. sigmoid(x) 함수가 유용하다는 것을 알 수 있습니다.
  2. $ \sigma'(x) = s(1-s)$ 를 계산합니다.

Expected Output:

sigmoid_derivative([1,2,3]) [ 0.19661193 0.10499359 0.04517666]

배열 재구성(reshaping)

딥 러닝에서 자주 사용되는 두 가지 일반적인 numpy 함수는 np.shape() 와 np.reshape()입니다.

예를 들어, 컴퓨터 과학에서 이미지는 $(길이,높이,깊이=3)$ 모양의 3D 배열로 표현됩니다. 그러나 이미지를 알고리즘의 입력으로 읽으면 $(length * height * 3, 1)$ 모양의 벡터로 변환합니다. 즉, 3D 배열을 1D 벡터로 "풀거나" 모양을 변경합니다.

(5) 연습 : 입력 모양 (길이, 높이, 3)을 취하고, (길이*높이*3, 1) 형태의 벡터를 반환하는 image2vector()를 구현합니다. 예를 들어, 모양 (a, b, c)의 배열 v를 모양의 벡터 (a*b,c)로 재구성하려면 다음을 수행하십시오.

v = v.reshape((v.shape[0] * v.shape[1], v.shape[2])) # v.shape[0] = a; v.shape[1] = b; v.shape[2] = c

이미지의 크기를 상수로 하드 코딩하지 마십시오. 대신 image.shape[0] 등으로 필요한 양을 찾으십시오.

Expected Output:

image2vector(image) [[ 0.67826139] [ 0.29380381] [ 0.90714982] [ 0.52835647] [ 0.4215251 ] [ 0.45017551] [ 0.92814219] [ 0.96677647] [ 0.85304703] [ 0.52351845] [ 0.19981397] [ 0.27417313] [ 0.60659855] [ 0.00533165] [ 0.10820313] [ 0.49978937] [ 0.34144279] [ 0.94630077]]

1.4 행 정규화

머신러닝 및 딥러닝에서 사용하는 또 다른 일반적인 기술은 데이터를 정규화하는 것입니다. 경사하강법은 정규화 후 더 빨리 수렴하기 때문에 종종 더 나은 성능으로 이어집니다. 여기서 정규화란 x를 $\frac {x}{\| x \|} $ (x의 각 행 벡터를 그것의 크기(norm)로 나눕니다).

예를 들어 $$x = \begin{bmatrix} 0 & 3 & 4 \\ 2 & 6 & 4 \\ \end{bmatrix}\tag{3}$$ 이면, 그 행들의 크기는 $$\| x\| = \text{np.linalg.norm}(x, \text{axis}=1, \text{keepdims}=True) = \begin{bmatrix} 5 \\ \sqrt{56} \\ \end{bmatrix}\tag{4} $$ 가 되고, 따라서 정규화는 다음과 같다. $$ \text{x_normalized} = \frac{x}{\| x\|} = \begin{bmatrix} 0 & \frac{3}{5} & \frac{4}{5} \\ \frac{2}{\sqrt{56}} &\frac{6}{\sqrt{56}}& \frac{4}{\sqrt{56}} \\ \end{bmatrix}\tag{5}$$

다양한 크기의 행렬로 나눌 수 있으며 잘 작동합니다 : 이것을 브로드캐스팅(broadcasting)이라고 하며, 이 과제의 마지막 부분에서 이에 대해 배울 것입니다.

(6) 연습 : normalizeRows()를 구현하여 행렬의 행을 정규화하십시오. 이 함수를 입력 행렬 x에 적용한 후 x의 각 행은 단위 길이(길이가 1인)의 벡터여야 합니다.

Expected Output:

normalizeRows(x) [[ 0. 0.6 0.8 ] [ 0.13736056 0.82416338 0.54944226]]

참고 : normalizeRows( )에서 x_norm 및 x의 모양을 출력한 다음 평가를 다시 실행할 수 있습니다. 모양이 다르다는 것을 알게 될 것입니다. x_norm이 x의 각 행의 norm을 취한다는 점을 감안할 때 이것은 정상입니다. 따라서 x_norm에는 동일한 수의 행이 있지만 열은 1 개뿐입니다. 그렇다면 x를 x_norm으로 나눌 때 어떻게 작동했을까요? 이것을 broadcast 라고 하는데 지금부터 이야기하겠습니다!

1.5 브로드캐스트 및 softmax 함수

numpy에서 이해해야 할 매우 중요한 개념은 "브로드캐스트"입니다. 서로 다른 모양의 배열 간에 수학적 연산을 수행하는 데 매우 유용합니다. 브로드캐스트에 대한 자세한 내용은 공식 브로드캐스트 문서를 참조하세요.

(7) 연습 : numpy를 사용하여 softmax 함수를 구현합니다. 알고리즘이 둘 이상의 클래스를 분류해야 할 때 사용되는 정규화 함수로 소프트 맥스를 생각할 수 있습니다. 이 전문 과정의 두 번째 과정에서 소프트맥스에 대해 자세히 알아 봅니다.

지시 :

참고

"훈련 예제 수"를 나타내는데 "m"이 사용되며, 각 훈련 예제는 행렬의 각 열에 있습니다. 또한 각 특징(feature)은 각 행에 있습니다 (각 행에는 동일한 특징에 대한 데이터가 있음). Softmax 는 각 훈련 예제의 모든 특징들에 대해 수행되어야 하므로 Softmax는 열에 대해 수행됩니다 (이 과정의 뒷부분에서 해당 표현으로 전환하면).

그러나, 이 코딩 연습에서는 Python에 익숙해지는 데 초점을 맞추고 있으므로 일반적인 수학 표기법 $ m \times n $을 사용합니다. 여기서 $ m $는 행 수이고 $ n $는 열 수입니다.

Expected Output:

softmax(x) [[ 9.80897665e-01 8.94462891e-04 1.79657674e-02 1.21052389e-04 1.21052389e-04] [ 8.78679856e-01 1.18916387e-01 8.01252314e-04 8.01252314e-04 8.01252314e-04]]

주의 :

위의 x_exp, x_sum 및 s의 모양을 인쇄하고 평가 셀을 다시 실행하면 x_sum의 모양이 (2,1)이고 x_exp 및 s의 모양이 (2,5)임을 알 수 있습니다. x_exp / x_sum은 파이썬 브로드케스트로 인해 작동합니다. 축하합니다! 이제 python numpy에 대해 꽤 잘 이해하고 딥 러닝에서 사용할 몇 가지 유용한 기능을 구현했습니다.

2) 벡터화(Vectorization)

딥 러닝에서는 매우 큰 데이터 세트를 다룹니다. 따라서 계산에 최적화되지 않은 함수는 알고리즘에서 큰 병목 현상이 될 수 있으며 실행하는 데 오랜 시간이 걸리는 모델이 생성 될 수 있습니다. 코드가 계산적으로 효율적인지 확인하려면 벡터화를 사용합니다. 예를 들어, dot/outer/element-wise 곱의 다음 구현 간의 차이점을 살펴보십시오.

인식된 것처럼, 벡터화된 구현은 훨씬 깨끗하고 효율적입니다. 더 큰 벡터/행렬의 경우 실행 시간의 차이가 더욱 커집니다.

np.dot()는 행렬-행렬 또는 행렬-벡터 곱셈을 수행합니다. 이것은 요소별 곱셈을 수행하는 np.multiply() 및 연산자 (Matlab/Octave의 .와 동일)와 다릅니다.

2.1 L1 및 L2 손실 함수 구현

(8) 연습 : L1 손실의 numpy 벡터화된 버전을 구현합니다. 함수 abs(x) (x의 절대 값)가 유용하다는 것을 알 수 있습니다.

참조:

Expected Output:

L1 1.1

(9) 연습 : L2 손실의 numpy 벡터화된 버전을 구현합니다. L2 손실을 구현하는 방법에는 여러 가지가 있지만 np.dot() 함수가 유용할 수 있습니다. 참고로 $x=[x_1, x_2, ..., x_n]$ 이면 np.dot(x,x)=$ \sum_{j=0}^n x_j^{2} 입니다.

L2 손실은 다음과 같이 정의됩니다: $$\begin{align*} L_2(\hat{y},y) = \sum_{i=0}^m(\hat{y}^{(i)} - y^{(i)})^2 \end{align*}\tag{7}$$

Expected Output:

L2 0.43

이 과제를 완료한 것을 축하합니다. 이 작은 준비 운동이 향후 과제에 도움이 되기를 바랍니다. 더 흥분되고 흥미로울 것입니다!